﻿/**************************************************************
 *
 * 唯一标识：dab05173-83b5-4919-b2b2-2932da3082a4
 * 命名空间：Sgr.Generator.Segment
 * 创建时间：2024/6/20 9:57:06
 * 机器名称：DESKTOP-HJ4OAG9
 * 创建者：CocoYuan
 * 电子邮箱：fengqinhua2016@163.com
 * 描述：
 *
 **************************************************************/

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Sgr.Exceptions;
using Sgr.Generator.Segment.Entities;
using Sgr.Generator.Segment.Storage;
using Sgr.Threading;
using System.Collections.Concurrent;
using System.Diagnostics;

namespace Sgr.Generator.Segment
{
    public class SegmentNumIdGenerator : ISegmentNumIdGenerator
    {
        public const string DEFAULT_KEY = "SGR";
        public const string DEFAULT_TEST_KEY = "SGR.TEST";

        /// <summary>
        /// 标识号段生成器是否已经初始化
        /// </summary>
        private AtomicBoolean _isInitComplete;

        /// <summary>
        /// 更新号段缓存的时间间隔
        /// </summary>
        private readonly TimeSpan _updateInterval;

        /// <summary>
        /// 定期更新任务是否已启动标志
        /// </summary>
        private int _periodicStarted = 0;

        /// <summary>
        /// 正在运行的后台任务数量
        /// </summary>
        private int _activeBackgroundTaskCount = 0;

        /// <summary>
        /// 日志记录器
        /// </summary>
        private readonly ILogger<SegmentNumIdGenerator> _logger;

        /// <summary>
        /// 标识当前类是否已释放
        /// </summary>
        private volatile bool _disposed;

        /// <summary>
        /// 释放当前类的锁
        /// </summary>
        private readonly object _disposeLock = new object();

        /// <summary>
        /// 号段缓存
        /// </summary>
        private ConcurrentDictionary<string, GenSegmentBuffer> cache;

        /// <summary>
        /// 负责处理后台定期更新任务的令牌
        /// </summary>
        private readonly CancellationTokenSource _backgroundCts;

        /// <summary>
        /// 用于控制从数据库中更新号段信息的信号量（确保并发环境中该操作仅有一个线程可用）
        /// </summary>
        private System.Threading.SemaphoreSlim slimlock;

        /// <summary>
        /// 号段数据存储
        /// </summary>
        private readonly ISegmentEntityDataStorage _genSegmentDataStorage;

        /// <summary>
        /// 配置选项
        /// </summary>
        private readonly SegmentNumIdGeneratorOptions _options;

        public SegmentNumIdGenerator(
            ISegmentEntityDataStorage genSegmentDataStorage,
            ILogger<SegmentNumIdGenerator> logger,
            IOptions<SegmentNumIdGeneratorOptions> options)
        {
            _disposed = false;
            _isInitComplete = new AtomicBoolean(false);

            _options = options.Value;
            _updateInterval = _options.UpdateIntervalSeconds <= 10 ? TimeSpan.Zero : TimeSpan.FromSeconds(_options.UpdateIntervalSeconds);

            _genSegmentDataStorage = genSegmentDataStorage ?? throw new ArgumentNullException(nameof(genSegmentDataStorage));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));

            cache = new ConcurrentDictionary<string, GenSegmentBuffer>();
            slimlock = new SemaphoreSlim(1, 1);
            _backgroundCts = new CancellationTokenSource();
        }

        /// <summary>
        /// 初始化号段生成器
        /// <param name="cancellationToken">取消令牌</param>
        /// </summary>
        /// <returns>初始化是否成功</returns>
        public async Task<bool> InitAsync(CancellationToken cancellationToken = default)
        {
            ThrowIfDisposed();

            // 双重检查锁定模式确保线程安全初始化
            if (_isInitComplete.Get())
                return true;

            await slimlock.WaitAsync(cancellationToken).ConfigureAwait(false);
            try
            {
                // 1. 检查是否已经初始化
                if (_isInitComplete.Get())
                    return true;

                _logger.LogInformation("Starting segment generator initialization...");

                // 2. 确保数据库表结构存在
                _logger.LogDebug("Ensuring segment table exists...");
                await _genSegmentDataStorage.CreateTableIfNotExist(cancellationToken).ConfigureAwait(false);

                // 3. 使用超时控制的初始化操作
                //using var initCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                //initCts.CancelAfter(TimeSpan.FromSeconds(30)); // 设置30秒超时

                // 4. 初始化号段缓存
                _logger.LogDebug("Loading segment cache from database...");
                await UpdateCacheFromDb(cancellationToken).ConfigureAwait(false);

                // 5. 启动定期更新任务（可配置）
                if (_updateInterval > TimeSpan.Zero)
                {
                    _logger.LogDebug("Starting periodic segment cache update task (interval={IntervalSeconds}s)", _options.UpdateIntervalSeconds);
                    StartPeriodicUpdate();
                }

                // 6. 设置初始化完成标志参数验证和初始化检查
                _isInitComplete.Set(true);

                _logger.LogInformation("Segment generator initialized successfully");
                return true;
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception ex)
            {
                // 初始化失败 → 标志保持 false（不需显式回滚）
                _logger.LogError(ex, "SegmentNumIdGenerator initialization failed");
                throw;
            }
            finally
            {
                slimlock.Release();
            }
        }

        /// <summary>
        /// 生成不重复的长整型唯一标识
        /// </summary>
        /// <param name="key">业务标识键</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>生成的唯一标识符</returns>
        /// <exception cref="BusinessException">当生成器未初始化或标识键不存在时抛出</exception>
        /// <exception cref="OperationCanceledException">当操作被取消时抛出</exception>
        public async Task<long> GetUniqueIdAsync(string key = "", CancellationToken cancellationToken = default)
        {
            // 1. 参数验证和初始化检查
            ThrowIfDisposed();
            cancellationToken.ThrowIfCancellationRequested();

            if (!_isInitComplete.Get())
            {
                if (!await InitAsync(cancellationToken).ConfigureAwait(false))
                {
                    throw new BusinessException("号段生成器初始化失败，请检查数据库连接是否正常");
                }
            }

            if (string.IsNullOrEmpty(key))
            {
                key = DEFAULT_KEY;
            }

            try
            {
                // 2. 获取或初始化缓存的号段
                GenSegmentBuffer buffer = await GetOrInitBuffer(key, cancellationToken).ConfigureAwait(false);
                // 3. 从缓存的号段中获取ID
                return await GetIdFromBufferAsync(buffer, cancellationToken).ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                // 上层取消：不作为错误
                throw;
            }
            catch (BusinessException)
            {
                // 保持调用方可识别业务异常
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "GetUniqueIdAsync failed: {Key}", key);
                throw;
            }
        }

        /// <summary>
        /// 获取或初始化号段缓存
        /// <param name="key">业务标识键</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// </summary>
        private async Task<GenSegmentBuffer> GetOrInitBuffer(string key, CancellationToken cancellationToken)
        {
            ThrowIfDisposed();
            cancellationToken.ThrowIfCancellationRequested();

            if (!cache.TryGetValue(key, out GenSegmentBuffer? buffer) || buffer == null)
            {
                throw new BusinessException($"号段生成器中不存在Key: {key}");
            }

            // 如果缓存未初始化，进行初始化
            if (!buffer.InitOk)
            {
                await InitializeBuffer(buffer, key, cancellationToken).ConfigureAwait(false);
            }

            return buffer;
        }

        /// <summary>
        /// 初始化号段缓存
        /// </summary>
        private async Task InitializeBuffer(GenSegmentBuffer buffer, string key, CancellationToken cancellationToken)
        {
            ThrowIfDisposed();
            cancellationToken.ThrowIfCancellationRequested();

            // 快速路径
            if (buffer.InitOk)
                return;

            // 抢占初始化权（仅 NotStarted / Failed 可进入）
            if (buffer.TryBeginInitialization())
            {
                long startTicks = Stopwatch.GetTimestamp();
                try
                {
                    await UpdateSegmentFromDb(buffer.GetCurrentGenSegment(), cancellationToken).ConfigureAwait(false);
                    buffer.MarkInitializationSucceeded();

                    _logger.LogInformation("Segment buffer initialized: {Key}, elapsed={ElapsedMs:F2}ms",
                        key, ElapsedMilliseconds(startTicks));
                    return;
                }
                catch (OperationCanceledException)
                {
                    buffer.MarkInitializationFailed();
                    throw;
                }
                catch (BusinessException)
                {
                    buffer.MarkInitializationFailed();
                    throw;
                }
                catch (Exception ex)
                {
                    buffer.MarkInitializationFailed();
                    _logger.LogError(ex, "Segment buffer initialization failed: {Key}", key);
                    throw new BusinessException($"初始化号段缓存失败: {key}", ex);
                }
            }

            // 其它并发线程：等待占位线程完成
            await WaitForInitializationCompletionAsync(buffer, key, cancellationToken).ConfigureAwait(false);

            if (!buffer.InitOk)
                throw new BusinessException($"号段缓存初始化失败: {key}，状态={buffer.InitState}");
        }

        /// <summary>
        /// 等待缓冲初始化完成（自旋 + 渐进退避 + 超时标记失败）
        /// </summary>
        private async Task WaitForInitializationCompletionAsync(GenSegmentBuffer buffer, string key, CancellationToken cancellationToken)
        {
            long startTicks = Stopwatch.GetTimestamp();

            int timeoutMs = _options.UpdateSegmentFromDb_TimeOut_Milliseconds;
            if (timeoutMs < 800) timeoutMs = 800;

            int spinCount = 0;
            int delayMs = 5; // 初始退避

            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var state = buffer.InitState;
                if (state == GenSegmentBuffer.BufferInitState.Succeeded ||
                    state == GenSegmentBuffer.BufferInitState.Failed)
                    return;

                // 自旋阶段（少量快速等待提高成功概率）
                if (spinCount < 64)
                {
                    Thread.SpinWait(32 * (spinCount + 1));
                    spinCount++;
                }
                else
                {
                    await Task.Delay(delayMs, cancellationToken).ConfigureAwait(false);
                    // 渐进退避，封顶
                    if (delayMs < 50) delayMs *= 2;
                }

                double elapsedMs = ElapsedMilliseconds(startTicks);
                if (elapsedMs > timeoutMs)
                {
                    _logger.LogWarning("Wait initialization timeout: {Key}, elapsed={ElapsedMs:F2}ms, state={State}",
                        key, elapsedMs, state);
                    return;
                }
            }
        }

        /// <summary>
        /// 从号段缓存中获取ID
        /// </summary>
        private async Task<long> GetIdFromBufferAsync(GenSegmentBuffer buffer, CancellationToken cancellationToken)
        {
            ThrowIfDisposed();
            cancellationToken.ThrowIfCancellationRequested();

            const int MAX_RETRY_COUNT = 3;
            int retryCount = 0;

            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();

                // 检查熔断状态
                if (buffer.IsCircuitBreaking())
                    throw new BusinessException($"键 {buffer.Key} 暂时不可用，数据库访问已熔断，请稍后重试");

                try
                {
                    return GetIdFromSegmentBuffer(buffer, cancellationToken);
                }
                catch (BusinessException) when (retryCount < MAX_RETRY_COUNT)
                {
                    retryCount++;
                    _logger.LogWarning($"Failed to get ID from segment, retrying ({retryCount}/{MAX_RETRY_COUNT}): {buffer.Key}");
                    await Task.Delay(50 * retryCount, cancellationToken).ConfigureAwait(false); // 使用递增延迟
                    continue;
                }
            }
        }

        #region 从GenSegmentBuffer中取数

        /// <summary>
        /// 从号段缓冲区中获取ID 【分为快慢路径两种方式】
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public long GetIdFromSegmentBuffer(GenSegmentBuffer buffer, CancellationToken cancellationToken)
        {
            Check.NotNull(buffer, nameof(buffer));

            // 快速路径 - 尝试无锁获取ID
            var currentSegment = buffer.GetCurrentGenSegment();
            long value = currentSegment.PreIncrementValue();
            if (value < currentSegment.Max)
            {
                // 非阻塞方式检查是否需要后台加载下一个号段
                if (!buffer.NextReady
                    && !buffer.IsThreadRunning()
                    && currentSegment.CheckUseRate()
                    && buffer.ChangeThreadStatuToRunning())
                {
                    TriggerNextSegmentLoad(buffer);
                }
                return value;
            }

            // 慢路径 - 需要获取锁并可能切换号段
            return GetIdWithLocking(buffer, cancellationToken);
        }

        // 分离需要锁的逻辑到单独方法
        private long GetIdWithLocking(GenSegmentBuffer buffer, CancellationToken cancellationToken)
        {
            int attempt = 0;

            long startTicks = Stopwatch.GetTimestamp();
            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();

                // 定期检查熔断（避免无意义等待）
                if (attempt % 64 == 0 && buffer.IsCircuitBreaking())
                    throw new BusinessException($"键 {buffer.Key} 处于熔断状态，切段等待中止");

                var segment = buffer.GetCurrentGenSegment();
                long fastValue = segment.PreIncrementValue();
                if (fastValue < segment.Max)
                {
                    return fastValue; // 快路径重入
                }

                // 当前段耗尽：尝试切段
                if (buffer.NextReady)
                {
                    bool lockTaken = false;
                    try
                    {
                        // 非阻塞快速尝试
                        if (Monitor.TryEnter(buffer.SyncRoot, Math.Min(1000, _options.BufferRwTimeout)))
                        {
                            lockTaken = true;

                            // 双重检查
                            if (buffer.NextReady)
                            {
                                buffer.SwitchPos();
                                buffer.NextReady = false;

                                // 从新号段获取ID
                                var next = buffer.GetCurrentGenSegment();
                                long v = next.PreIncrementValue();
                                if (v < next.Max)
                                    return v;

                                // 新段意外耗尽（极少）→ 触发再次加载
                                if (!buffer.IsThreadRunning() && buffer.ChangeThreadStatuToRunning())
                                    TriggerNextSegmentLoad(buffer);
                            }
                        }
                    }
                    finally
                    {
                        if (lockTaken)
                            Monitor.Exit(buffer.SyncRoot);
                    }
                }
                else
                {
                    // 下一段未准备，确保后台加载
                    if (!buffer.IsThreadRunning() && buffer.ChangeThreadStatuToRunning())
                        TriggerNextSegmentLoad(buffer);
                }

                attempt++;
                // 退避策略
                if (attempt <= 8)
                    Thread.SpinWait(32 * attempt);  // 少量自旋：CPU 局部缓存热，极短等待
                else if (attempt <= 64)
                    Thread.Yield();                 // 进入调度级让出
                else
                    Thread.Sleep(1);                // 长期等待，降低 CPU 占用

                double elapsedMs = ElapsedMilliseconds(startTicks);
                // 检查是否超过等待限制
                if (attempt >= _options.GetId_Attempt_Limit || elapsedMs >= _options.GetId_TimeOut_Milliseconds)
                {
                    _logger.LogError("Segment switch wait exceeded limits: {Key}, attempts={Attempt}, elapsedMs={Elapsed}",
                        buffer.Key, attempt, elapsedMs);
                    throw new BusinessException($"号段 {buffer.Key} 切换耗时过长（{elapsedMs:F2}ms，attempt={attempt}），已中止。");
                }
            }
        }

        /// <summary>
        /// 触发异步加载下一个号段
        /// </summary>
        private void TriggerNextSegmentLoad(GenSegmentBuffer buffer)
        {
            if (_backgroundCts.IsCancellationRequested || _disposed)
                return;

            // 外部已通过 ChangeThreadStatuToRunning 设置运行标志
            Interlocked.Increment(ref _activeBackgroundTaskCount);
            Task.Run(async () =>
            {
                long startTicks = Stopwatch.GetTimestamp();
                string key = buffer.Key;

                int timeout = _options.UpdateSegmentFromDb_TimeOut_Milliseconds;
                if (timeout < 800)
                    timeout = 800;

                using var timeoutCts = new CancellationTokenSource(TimeSpan.FromMilliseconds(timeout));
                using var linked = CancellationTokenSource.CreateLinkedTokenSource(timeoutCts.Token, _backgroundCts.Token);
                var ct = linked.Token;

                _logger.LogDebug("Begin loading next segment: {Key}, timeout={TimeoutMs}ms", key, timeout);

                try
                {
                    if (buffer.IsCircuitBreaking())
                    {
                        _logger.LogWarning("Abort loading next segment due to circuit breaker: {Key}", key);
                        return;
                    }

                    var next = buffer.GetNextGenSegment();

                    await UpdateSegmentFromDb(next, ct).ConfigureAwait(false);

                    // 发布 NextReady：尝试最多两次
                    PublishNextReadyWithRetry(buffer, key);

                    _logger.LogInformation("Next segment loaded: {Key}, elapsedMs={ElapsedMs}", key, ElapsedMilliseconds(startTicks));
                }
                catch (OperationCanceledException)
                {
                    _logger.LogWarning("Load next segment canceled: {Key}", key);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Load next segment failed: {Key}", key);
                }
                finally
                {
                    buffer.ChangeThreadStatuToStop();
                    Interlocked.Decrement(ref _activeBackgroundTaskCount);
                }
            });
        }

        /// <summary>
        /// 发布 NextReady 状态，带重试机制
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="key"></param>
        private void PublishNextReadyWithRetry(GenSegmentBuffer buffer, string key)
        {
            const int MAX_ATTEMPTS = 2;
            for (int attempt = 1; attempt <= MAX_ATTEMPTS; attempt++)
            {
                bool lockTaken = false;
                try
                {
                    if (Monitor.TryEnter(buffer.SyncRoot, _options.BufferRwTimeout))
                    {
                        lockTaken = true;
                        buffer.NextReady = true;
                        _logger.LogDebug("Publish NextReady success: {Key}, attempt={Attempt}", key, attempt);
                        return;
                    }
                    else
                    {
                        if (attempt < MAX_ATTEMPTS)
                        {
                            _logger.LogWarning("Publish NextReady lock timeout (will retry): {Key}, attempt={Attempt}", key, attempt);
                            Thread.Sleep(10); // 小退避
                        }
                        else
                        {
                            _logger.LogError("Publish NextReady failed after retries: {Key}", key);
                        }
                    }
                }
                finally
                {
                    if (lockTaken)
                        Monitor.Exit(buffer.SyncRoot);
                }
            }
        }

        /// <summary>
        /// 计算经过的毫秒数
        /// </summary>
        /// <param name="startTicks"></param>
        /// <returns></returns>
        private static double ElapsedMilliseconds(long startTicks)
        {
            return (Stopwatch.GetTimestamp() - startTicks) * 1000.0 / Stopwatch.Frequency;
        }

        #endregion 从GenSegmentBuffer中取数

        #region 从数据库更新号段信息

        /// <summary>
        /// 从数据库更新号段信息
        /// </summary>
        /// <param name="segment">要更新的号段</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>更新操作的任务</returns>
        /// <exception cref="ArgumentNullException">当segment为null时抛出</exception>
        /// <exception cref="OperationCanceledException">当操作被取消时抛出</exception>
        /// <exception cref="BusinessException">当熔断器触发时抛出</exception>
        private async Task UpdateSegmentFromDb(GenSegment segment, CancellationToken cancellationToken)
        {
            ThrowIfDisposed();
            cancellationToken.ThrowIfCancellationRequested();
            //Check.NotNull(segment, nameof(segment));

            GenSegmentBuffer buffer = segment.GetBuffer();
            string key = buffer.Key;

            // 检查熔断器状态
            if (buffer.IsCircuitBreaking())
            {
                DateTime? resetTime = buffer.CircuitResetTime;
                _logger.LogWarning("Key {Key} is in circuit breaking state, will reset at {ResetTime}",
                    key, resetTime?.ToString("o") ?? "unknown");
                throw new BusinessException($"键 {key} 暂时不可用，数据库访问已熔断，请稍后重试");
            }

            try
            {
                var segmentEntity = await UpdateSegmentEntityAsync(buffer, key, cancellationToken).ConfigureAwait(false);

                // 成功更新后重置错误计数
                if (buffer.ErrorCount > 0)
                {
                    buffer.ResetErrorCount();
                    _logger.LogInformation("Key {Key} successfully accessed database, error count reset", key);
                }

                // 计算本段起始值（设置为 max_id - latestStep，首个取值为 start+1）
                long startValue = segmentEntity.MaxId - buffer.LatestStep;
                if (startValue < 0)
                {
                    _logger.LogWarning("Start value corrected (<0). Key={Key}, MaxId={MaxId}, LatestStep={LatestStep}", key, segmentEntity.MaxId, buffer.LatestStep);
                    startValue = 0;
                }

                segment.SetValue(startValue);
                segment.Max = segmentEntity.MaxId;
                segment.Step = buffer.LatestStep;

                _logger.LogDebug("Successfully updated segment info: {Key}, MaxId: {MaxId}, Step: {Step}",
                    key, segmentEntity.MaxId, buffer.LatestStep);
            }
            catch (OperationCanceledException)
            {
                throw; // 取消直接向上抛
            }
            catch (Exception ex) when (ex is not OperationCanceledException)
            {
                _logger.LogError(ex, "Failed to update segment info: {Key}", key);

                // 数据库错误触发熔断保护
                long currentErrorCount = buffer.IncrementErrorCount();
                _logger.LogWarning("Key {Key} database access failed, current error count: {ErrorCount}/{Threshold}",
                        key, currentErrorCount, _options.ErrorThresholdBeforeTrip);

                // 检查是否需要触发熔断器
                if (currentErrorCount >= _options.ErrorThresholdBeforeTrip)
                {
                    buffer.TripCircuit(_options.Circuit_Reset_Seconds);
                    _logger.LogError("Key {Key} error count reached threshold, circuit breaker triggered, reset time: {ResetSeconds} seconds",
                        key, _options.Circuit_Reset_Seconds);
                }

                throw; // 重新抛出原始异常
            }
        }

        private async Task<SegmentEntity> UpdateSegmentEntityAsync(
                    GenSegmentBuffer buffer,
                    string key,
                    CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // 路径1：未初始化（InitOk=false）
            if (!buffer.InitOk)
            {
                return await InitializeOrFirstUpdateAsync(buffer, key, isFirst: true, cancellationToken).ConfigureAwait(false);
            }

            // 路径2：首次更新时间戳 == 0
            if (buffer.UpdateTimestamp == 0)
            {
                return await InitializeOrFirstUpdateAsync(buffer, key, isFirst: true, cancellationToken).ConfigureAwait(false);
            }

            // 路径3：常规更新
            return await UpdateNormalSegmentEntity(buffer, key, cancellationToken).ConfigureAwait(false);
        }

        /// <summary>
        /// 初始化或首次更新（统一逻辑）
        /// </summary>
        private async Task<SegmentEntity> InitializeOrFirstUpdateAsync(
            GenSegmentBuffer buffer,
            string key,
            bool isFirst,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var entity = await _genSegmentDataStorage
                .UpdateMaxIdAndGetGenSegmentAsync(key, cancellationToken)
                .ConfigureAwait(false);

            // 基本校验
            if (entity.Step < _options.MinStepLowerBound || entity.Step > _options.MaxStepUpperBound)
                throw new BusinessException($"号段 {key} 步长非法：{entity.Step}");

            // 设置缓冲区步长（覆盖为数据库真实值）
            if (entity.MaxId <= 0)
            {
                _logger.LogWarning("Segment entity MaxId <= 0 (may be first allocation). Key={Key}, MaxId={MaxId}", key, entity.MaxId);
                //throw new BusinessException($"号段 {key} 最大值非法：{entity.MaxId}");
            }

            buffer.LatestStep = entity.Step;
            // 初始化或首次更新必须设置 UpdateTimestamp
            buffer.UpdateTimestamp = CurrentTimeMillis();

            _logger.LogInformation("Segment {Mode} update: Key={Key}, MaxId={MaxId}, Step={Step}",
                isFirst ? "initial" : "first", key, entity.MaxId, entity.Step);

            return entity;
        }

        /// <summary>
        /// 常规更新号段实体（动态步长演化）
        /// </summary>
        private async Task<SegmentEntity> UpdateNormalSegmentEntity(
            GenSegmentBuffer buffer,
            string key,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            long now = CurrentTimeMillis();
            long lastTs = buffer.UpdateTimestamp;
            long duration = now - lastTs;
            if (duration < 0)
            {
                _logger.LogWarning("Clock anomaly detected (duration<0). Forcing duration=0. Key={Key}, LastTs={LastTs}, Now={Now}", key, lastTs, now);
                duration = 0;
            }

            int oldStep = buffer.LatestStep;
            int overrideStep = CalculateNextStep(buffer, duration);

            // DB 调用（可能返回与请求不同的实际步长）
            var entity = await _genSegmentDataStorage
                .UpdateMaxIdAndGetGenSegmentAsync(key, overrideStep, cancellationToken)
                .ConfigureAwait(false);

            // 最近一次使用的步长
            buffer.LatestStep = overrideStep;

            // 更新缓冲区（使用数据库最终步长作为新的基准）
            buffer.UpdateTimestamp = now;

            _logger.LogInformation(
                "Segment update: Key={Key}, DurationMs={DurationMs}, OldStep={OldStep}, OverrideStep={OverrideStep}, PersistStep={PersistStep}, MaxId={MaxId}, Changed={Changed}",
                key, duration, oldStep, overrideStep, entity.Step, entity.MaxId, oldStep != overrideStep);

            return entity;
        }

        /// <summary>
        /// 计算下一次扩容步长（不修改持久化步长）
        /// </summary>
        private int CalculateNextStep(GenSegmentBuffer buffer, long duration)
        {
            int min = _options.MinStepLowerBound;
            int max = _options.MaxStepUpperBound;

            // 当前步长归一
            int current = buffer.LatestStep;
            if (current < min) current = min;
            if (current > max) current = max;

            long segDur = _options.SegmentDuration;
            if (segDur <= 0)
                return current; // 未启用动态时长策略 → 保持

            // 快速消耗：加倍
            if (duration < segDur)
            {
                long doubled = (long)current * 2;
                int candidate = doubled > max ? max : (int)doubled;
                return candidate;
            }

            // 低速消耗：减半
            if (duration > segDur * 2)
            {
                if (current <= min)
                    return current; // 已在下限

                int halved = current / 2;
                if (halved < min) halved = min;
                return halved;
            }

            // 中间区间：保持
            return current;
        }

        private static long CurrentTimeMillis()
        {
            return (long)(DateTime.UtcNow - Constant.UnixEpoch).TotalMilliseconds;
        }

        #endregion 从数据库更新号段信息

        #region 手动或定时更新号段列表集合

        /// <summary>
        /// 从数据库更新号段缓存
        /// <param name="cancellationToken"></param>
        /// </summary>
        /// <returns></returns>
        private async Task UpdateCacheFromDb(CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();
            _logger.LogInformation("Starting to update segment cache from database");

            try
            {
                // 1. 获取数据库中的标识集合
                var dbTagEnumerable = await _genSegmentDataStorage.GetIdsAsync(cancellationToken).ConfigureAwait(false);
                var dbTags = (dbTagEnumerable ?? Enumerable.Empty<string>()).ToHashSet(StringComparer.Ordinal);

                if (dbTags.Count == 0)
                {
                    // 当前行为：数据库为空则保持现有缓存（防止临时故障导致整体清空）
                    // 若希望真实同步，可改为：
                    // foreach (var k in cache.Keys) cache.TryRemove(k, out _);
                    _logger.LogInformation("Segment cache sync: database returned 0 identifiers, keep existing cache (count={Count})", cache.Count);
                    return;
                }

                // 2. 获取当前缓存的标识集合的快照
                var cacheTags = new HashSet<string>(cache.Keys, StringComparer.Ordinal);

                // 4. 计算需要新增和删除的标识
                var tagsToAdd = dbTags.Except(cacheTags).ToList();
                var tagsToRemove = cacheTags.Except(dbTags).ToList();

                // 5. 批量处理新增的标识
                foreach (var tag in tagsToAdd)
                {
                    try
                    {
                        var genSegment = new GenSegmentBuffer(tag);
                        var segment = genSegment.GetCurrentGenSegment();
                        segment.SetValue(0);
                        //segment.Max = 0;
                        //segment.Step = 0;

                        if (cache.TryAdd(tag, genSegment))
                        {
                            _logger.LogInformation($"  - Successfully added new segment cache: {tag}");
                        }
                        else
                        {
                            _logger.LogWarning($"  - Failed to add segment cache, may already exist: {tag}");
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "Error processing new segment: {tag}", tag);
                    }
                }

                // 6. 批量处理需要删除的标识
                foreach (var tag in tagsToRemove)
                {
                    try
                    {
                        if (cache.TryRemove(tag, out var removed))
                        {
                            _logger.LogInformation($"  - Successfully removed expired segment cache: {tag}");
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "Error removing expired segment: {tag}", tag);
                    }
                }

                // 8. 输出更新统计信息
                _logger.LogInformation($"Segment cache update completed. Added: {tagsToAdd.Count}, Removed: {tagsToRemove.Count}, Total: {cache.Count}");
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Unexpected error occurred while updating segment cache");
                throw; // 重要错误需要向上传递
            }
        }

        /// <summary>
        /// 启动定期更新任务
        /// </summary>
        private void StartPeriodicUpdate()
        {
            if (_updateInterval <= TimeSpan.Zero)
                return;

            // 防重复启动
            if (Interlocked.CompareExchange(ref _periodicStarted, 1, 0) != 0)
            {
                _logger.LogWarning("Periodic update already started, skip duplicate start.");
                return;
            }

            Interlocked.Increment(ref _activeBackgroundTaskCount);
            Task.Run(async () =>
            {
                _logger.LogDebug("Periodic update task started. Interval={IntervalMs}ms.", _updateInterval.TotalMilliseconds);
                try
                {
                    using var timer = new PeriodicTimer(_updateInterval);
                    while (await timer.WaitForNextTickAsync(_backgroundCts.Token))
                    {
                        if (_disposed)
                            break;

                        try
                        {
                            await UpdateCacheFromDb(_backgroundCts.Token).ConfigureAwait(false);
                        }
                        catch (OperationCanceledException)
                        {
                            break;
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(ex, "定期更新号段缓存时发生错误");
                        }
                    }
                }
                finally
                {
                    _logger.LogDebug("Periodic update task stopped.");
                    Interlocked.Decrement(ref _activeBackgroundTaskCount);
                }
            });
        }

        #endregion 手动或定时更新号段列表集合

        #region IDisposable

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                lock (_disposeLock)
                {
                    if (!_disposed)
                    {
                        if (disposing)
                        {
                            try
                            {
                                // 1. 首先停止接受新请求
                                _isInitComplete.Set(false);

                                // 2. 取消并等待后台任务完成
                                _backgroundCts?.Cancel();

                                // 3. 等待所有活跃操作完成
                                var sw = Stopwatch.StartNew();
                                while (Interlocked.CompareExchange(ref _activeBackgroundTaskCount, 0, 0) != 0 && sw.ElapsedMilliseconds < 2000)
                                {
                                    Thread.Sleep(50);
                                }
                                int remaining = Interlocked.CompareExchange(ref _activeBackgroundTaskCount, 0, 0);
                                if (remaining != 0)
                                {
                                    _logger.LogWarning("Background tasks did not stop within timeout. Remaining={Remaining}", remaining);
                                }

                                // 4. 更有序地清理和释放资源
                                DisposeManagedResources();
                            }
                            catch (Exception ex)
                            {
                                _logger?.LogError(ex, "释放资源时发生错误");
                            }
                        }

                        // 设置状态标志
                        _disposed = true;
                    }
                }
            }
        }

        // 分离资源释放逻辑
        private void DisposeManagedResources()
        {
            // 清理缓存资源
            cache?.Clear();

            // 按顺序释放各种资源
            slimlock?.Dispose();
            _backgroundCts?.Dispose();
        }

        /// <summary>
        /// 实现 IDisposable 接口
        /// </summary>
        public void Dispose()
        {
            // 释放托管和非托管资源
            Dispose(true);
            // 通知垃圾回收器不再调用终结器
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 终结器
        /// </summary>
        ~SegmentNumIdGenerator()
        {
            Dispose(false);
        }

        /// <summary>
        /// 检查对象是否已释放
        /// </summary>
        /// <exception cref="ObjectDisposedException">当对象已释放时抛出</exception>
        protected void ThrowIfDisposed()
        {
            ObjectDisposedException.ThrowIf(_disposed, this);
        }

        #endregion IDisposable
    }
}